package com.vegetable.modules.service.outbound.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vegetable.modules.entity.outbound.SalesOut;
import com.vegetable.modules.entity.outbound.SalesOutDeduction;
import com.vegetable.modules.entity.outbound.po.SalesOutDeductionAddPO;
import com.vegetable.modules.entity.outbound.po.SalesOutDeductionPO;
import com.vegetable.modules.entity.outbound.po.SalesOutDeductionUpdatePO;
import com.vegetable.modules.mapper.outbound.SalesOutDeductionMapper;
import com.vegetable.modules.mapper.outbound.SalesOutMapper;
import com.vegetable.modules.service.outbound.ISalesOutDeductionService;
import com.vegetable.modules.service.outbound.ISalesOutService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
@AllArgsConstructor
public class SalesOutDeductionServiceImpl extends ServiceImpl<SalesOutDeductionMapper, SalesOutDeduction> implements ISalesOutDeductionService {

    private SalesOutMapper salesOutMapper;

    private ISalesOutService salesOutService;
    @Override
    public IPage<SalesOutDeduction> selectPage(SalesOutDeductionPO po) {
        Page<SalesOutDeduction> page = new Page<>(po.getCurrent(), po.getSize());
        QueryWrapper<SalesOutDeduction> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(StrUtil.isNotBlank(po.getDocNo()), "doc_no", po.getDocNo());
        queryWrapper.eq(ObjectUtil.isNotNull(po.getDeductionType()), "deduction_type", po.getDeductionType());
        queryWrapper.eq(ObjectUtil.isNotNull(po.getDisposalType()), "disposal_type", po.getDisposalType());
        queryWrapper.eq("customer_id", po.getCustomerId());
        if(ObjectUtil.isNotNull(po.getOrderTimeStart())){
            queryWrapper.gt("order_time", DateUtil.beginOfDay(po.getOrderTimeStart()));
        }
        if(ObjectUtil.isNotNull(po.getOrderTimeEnd())){
            queryWrapper.lt("order_time", DateUtil.endOfDay(po.getOrderTimeEnd()));
        }
        queryWrapper.orderByDesc("customer_id");
        return baseMapper.selectPage(page, queryWrapper);
    }

    @Override
    public void addDeduction(SalesOutDeductionAddPO po) {
        SalesOut so = salesOutMapper.selectById(po.getOutId());
        if(ObjectUtil.isNull(so)){
            throw new RuntimeException("待处理的出库单不存在.");
        }
        SalesOutDeduction add = new SalesOutDeduction();
        BeanUtils.copyProperties(po, add);
        add.setOrderTime(so.getOrderTime());
        add.setDocNo(so.getDocNo());
        add.setCustomerId(so.getCustomerId());
        add.setCustomerName(so.getCustomerName());
        baseMapper.insert(add);
        updateSalesOutDeduction(po.getOutId());
    }

    @Override
    @Transactional
    public void batchAddDeduction(List<SalesOutDeductionAddPO> pos) {
        for(SalesOutDeductionAddPO po : pos){
            addDeduction(po);
        }
    }

    @Override
    public void updateDeduction(SalesOutDeductionUpdatePO po) {
        SalesOutDeduction updater = new SalesOutDeduction();
        BeanUtils.copyProperties(po, updater);
        baseMapper.updateById(updater);
        updateSalesOutDeduction(po.getOutId());
    }

    /**
     * 更新出库单的扣款总额/回款总额
     * @param outId
     */
    private void updateSalesOutDeduction(Long outId){
        List<SalesOutDeduction> deductionList = getSalesOutDeductionByOutId(outId);
        if(CollectionUtil.isNotEmpty(deductionList)){
            // 回款列表
            List<SalesOutDeduction> returnedList = deductionList.stream().filter(el ->el.getDeductionType() == 3).collect(Collectors.toList());
            // 扣款列表
            List<SalesOutDeduction> deductionedList = deductionList.stream().filter(el ->el.getDeductionType() == 0).collect(Collectors.toList());
            BigDecimal totalReturnedMoney = returnedList.stream().map(SalesOutDeduction::getDeductionMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal totalDeductionMoney = deductionedList.stream().map(SalesOutDeduction::getDeductionMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
            SalesOut out = new SalesOut();
            out.setId(outId);
            out.setDeductionMoney(totalDeductionMoney);
            out.setReceivedMoney(totalReturnedMoney);
            salesOutService.updateById(out);
        }

    }

    @Override
    public List<SalesOutDeduction> getSalesOutDeductionByOutId(Long outId) {
        QueryWrapper<SalesOutDeduction> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("out_id", outId);
        return baseMapper.selectList(queryWrapper);
    }

    @Override
    public List<SalesOutDeduction> getSalesOutDeductionByFCId(Long fcId) {
        QueryWrapper<SalesOutDeduction> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("fc_id", fcId);
        return baseMapper.selectList(queryWrapper);
    }
}
